{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import gc\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import re\n",
    "import time\n",
    "from scipy import stats\n",
    "import matplotlib.pyplot as plt\n",
    "import category_encoders as ce\n",
    "import networkx as nx\n",
    "import pickle\n",
    "from datetime import timedelta\n",
    "from gensim.models import Word2Vec\n",
    "from io import StringIO\n",
    "from tqdm import tqdm\n",
    "from sklearn.metrics import roc_curve\n",
    "from scipy.stats import chi2_contingency, pearsonr\n",
    "from sklearn.preprocessing import StandardScaler, OneHotEncoder, LabelEncoder\n",
    "from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer\n",
    "from sklearn.feature_extraction import FeatureHasher\n",
    "from sklearn.model_selection import StratifiedKFold, KFold, train_test_split, GridSearchCV\n",
    "from category_encoders import TargetEncoder\n",
    "from sklearn.decomposition import TruncatedSVD\n",
    "from autogluon.tabular import TabularDataset, TabularPredictor, FeatureMetadata\n",
    "from autogluon.features.generators import AsTypeFeatureGenerator, BulkFeatureGenerator, DropUniqueFeatureGenerator, FillNaFeatureGenerator, PipelineFeatureGenerator\n",
    "from autogluon.features.generators import CategoryFeatureGenerator, IdentityFeatureGenerator, AutoMLPipelineFeatureGenerator\n",
    "from autogluon.common.features.types import R_INT, R_FLOAT\n",
    "from autogluon.core.metrics import make_scorer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pd.set_option('display.max_rows', None)\n",
    "pd.set_option('display.max_columns', None)\n",
    "pd.set_option('display.max_info_columns', 2000)\n",
    "np.set_printoptions(threshold=np.inf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%config SqlMagic.autolimit=0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据导入"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open('./data/basic_final_features.pkl','rb') as f:\n",
    "    basic_final_features = pickle.load(f)\n",
    "    \n",
    "with open('./data/trdtal_final_features.pkl','rb') as f:\n",
    "    trdtal_final_features = pickle.load(f)\n",
    "    \n",
    "with open('./data/person_final_features.pkl','rb') as f:\n",
    "    person_final_features = pickle.load(f)\n",
    "    \n",
    "with open('./data/alter_final_features.pkl','rb') as f:\n",
    "    alter_final_features = pickle.load(f)\n",
    "    \n",
    "with open('./data/tax_final_features.pkl','rb') as f:\n",
    "    tax_final_features = pickle.load(f)\n",
    "    \n",
    "with open('./data/webdata_final_features.pkl','rb') as f:\n",
    "    webdata_final_features = pickle.load(f)\n",
    "    \n",
    "with open('./data/shareholder_final_features.pkl','rb') as f:\n",
    "    shareholder_final_features = pickle.load(f)\n",
    "    \n",
    "with open('./data/punished_final_features.pkl','rb') as f:\n",
    "    punished_final_features = pickle.load(f)\n",
    "    \n",
    "with open('./data/punishbreak_final_features.pkl','rb') as f:\n",
    "    punishbreak_final_features = pickle.load(f)\n",
    "    \n",
    "with open('./data/finalcase_final_features.pkl','rb') as f:\n",
    "    finalcase_final_features = pickle.load(f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "TARGET_T = pd.read_csv('../../contest/train/XW_ENTINFO_TARGET_T.csv')\n",
    "TARGET_B = pd.read_csv('../../contest/B/XW_ENTINFO_TARGET_B.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_data = pd.DataFrame()\n",
    "df_data_clean = pd.DataFrame()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_name = [basic_final_features, trdtal_final_features, person_final_features, alter_final_features, tax_final_features, webdata_final_features,\n",
    "            shareholder_final_features, punished_final_features, punishbreak_final_features, finalcase_final_features]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 通用函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 剔除函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def remove_sparse_columns(df, threshold=0.99):\n",
    "    sparse_cols = []\n",
    "    total_rows = df.shape[0]\n",
    "    \n",
    "    for col in df.columns:\n",
    "        # 计算缺失值或零值比例\n",
    "        zero_or_na_ratio = ((df[col].isna()) | (df[col] == 0)).sum() / total_rows\n",
    "        if zero_or_na_ratio > threshold:\n",
    "            sparse_cols.append(col)\n",
    "    \n",
    "    # 剔除稀疏列\n",
    "    df = df.drop(columns=sparse_cols)\n",
    "    return df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 合并函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def merge_with_target(df_target, dfs):\n",
    "    df_merged = df_target.copy()\n",
    "    for df in dfs:\n",
    "        df_merged = df_merged.merge(df, on=\"CUST_NO\", how=\"left\")\n",
    "        #df_merged = handle_missing_values(df_merged)  # 每次合并后处理缺失值\n",
    "    #df_merged = remove_sparse_columns(df_merged)  # 合并后去除稀疏列\n",
    "    return df_merged"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 通用迭代训练函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_best_model(X_train, y_train, X_test, num_model_seed=2, seeds=None, fold=10, max_retries=3, \n",
    "                     time_limit=600, model_path_dir=\"ModelDir\", other_path=\"ModelOtherDir\"):\n",
    "    \"\"\"\n",
    "    使用AutoGluon对输入的训练集进行交叉验证和模型训练，自动选择最佳模型进行测试集预测。\n",
    "\n",
    "    参数：\n",
    "    - X_train: 训练集特征 (pd.DataFrame)\n",
    "    - y_train: 训练集标签 (pd.Series)\n",
    "    - X_test: 测试集特征 (pd.DataFrame)\n",
    "    - num_model_seed: 使用多少个不同的随机种子进行训练 (int)\n",
    "    - seeds: 随机种子列表 (list)\n",
    "    - fold: 交叉验证折数 (int)\n",
    "    - max_retries: 每折训练最大重试次数 (int)\n",
    "    - time_limit: 每次训练的时间限制，单位为秒 (int)\n",
    "\n",
    "    返回：\n",
    "    - test_predictions: 测试集预测结果 (pd.Series)\n",
    "    \"\"\"\n",
    "    if seeds is None:\n",
    "        seeds = [123, 1993]\n",
    "        #seeds = [1993, 123, 4096, 1015, 2008, 42]  # 默认的随机种子列表\n",
    "\n",
    "    # 保存每个种子、每折的交叉验证结果\n",
    "    oof_preds = np.zeros(len(X_train))\n",
    "    test_preds = np.zeros(len(X_test))\n",
    "    pred = []\n",
    "\n",
    "    # 保存模型信息\n",
    "    best_model_path = \"\"\n",
    "    best_ks_score = -np.inf\n",
    "\n",
    "    # 定义训练用超参数\n",
    "    hyperparameters = {\n",
    "        'XGB': {'learning_rate': 0.01},\n",
    "        'GBM': {'learning_rate': 0.01},\n",
    "        'CAT': {'learning_rate': 0.01},\n",
    "        # 其他模型的超参数可以在这里添加\n",
    "    }\n",
    "\n",
    "    # KS评分计算函数\n",
    "    def compute_ks(y_true, y_pred):\n",
    "        fpr, tpr, _ = roc_curve(y_true, y_pred)\n",
    "        ks_score = max(tpr - fpr)\n",
    "        return ks_score\n",
    "\n",
    "    # 记录开始时间\n",
    "    overall_start_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())\n",
    "\n",
    "    # 循环种子以训练多个模型\n",
    "    for model_seed in range(num_model_seed):\n",
    "        print(f\"-------------  当前随机种子：{seeds[model_seed]} -------------------------------\")\n",
    "        \n",
    "        skf = StratifiedKFold(n_splits=fold, shuffle=True, random_state=seeds[model_seed])\n",
    "        fold_oof_preds = np.zeros(len(X_train))\n",
    "        fold_test_preds = np.zeros(len(X_test))\n",
    "\n",
    "\n",
    "        for fold_idx, (train_idx, val_idx) in enumerate(skf.split(X_train, y_train)):\n",
    "            print(f\"---------------------------------------\")\n",
    "            print(f\"训练第 {fold_idx + 1} 折\")\n",
    "            \n",
    "            # 记录开始时间\n",
    "            fold_start_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())\n",
    "            print(f\"随机种子：{seeds[model_seed]}，训练第 {fold_idx + 1} 折，开始时间：{fold_start_time}\")\n",
    "\n",
    "            # 划分训练和验证数据\n",
    "            train_data = pd.concat([X_train.iloc[train_idx], y_train.iloc[train_idx]], axis=1)\n",
    "            val_data = pd.concat([X_train.iloc[val_idx], y_train.iloc[val_idx]], axis=1)\n",
    "\n",
    "            print(f\"训练集模型大小：{train_data.shape}\")\n",
    "            print(f\"验证集模型大小：{val_data.shape}\")\n",
    "\n",
    "            retries = 0\n",
    "            previous_ks_score = -np.inf\n",
    "            current_features = X_train.columns.tolist()\n",
    "\n",
    "            # 重试训练直到KS评分提升或达到最大重试次数\n",
    "            while retries < max_retries:\n",
    "                datename = time.strftime('%Y%m%d%H%M', time.localtime())\n",
    "                model_path = f'./{model_path_dir}/model_seed_{seeds[model_seed]}_fold_{fold_idx + 1}_retry_{retries}'\n",
    "                ag_leaderboard = pd.DataFrame()\n",
    "                predictor_auto = TabularPredictor(label='FLAG', eval_metric='roc_auc', path=model_path, verbosity=2).fit(\n",
    "                    train_data[current_features + ['FLAG']],\n",
    "                    #presets='best_quality',\n",
    "                    #time_limit=time_limit,\n",
    "                    hyperparameters=hyperparameters,\n",
    "                    excluded_model_types = ['FASTAI', 'NN_TORCH', 'NN_MXNET', 'NN', 'KNN']\n",
    "                )\n",
    "\n",
    "                # 验证集预测\n",
    "                val_data_copy = val_data[current_features + ['FLAG']].copy()\n",
    "                print(f\"验证集模型大小：{val_data_copy.shape}\")\n",
    "                \n",
    "                val_pred_proba = predictor_auto.predict_proba(val_data_copy)\n",
    "                \n",
    "                val_pred_proba1 = val_pred_proba.values\n",
    "                val_pred = val_pred_proba1[:, 1]\n",
    "                current_ks_score = compute_ks(val_data['FLAG'], val_pred)\n",
    "\n",
    "                ag_leaderboard = predictor_auto.leaderboard(val_data_copy, silent=True)\n",
    "                ag_leaderboard.to_csv(f\"./{other_path}/model_seed_{seeds[model_seed]}_fold_{fold_idx + 1}_retry_{retries}_leaderboard.csv\", index=False)\n",
    "\n",
    "                val_save_path = f\"./{other_path}/model_seed_{seeds[model_seed]}_fold_{fold_idx + 1}_retry_{retries}_validation.pkl\"\n",
    "                with open(val_save_path, 'wb') as file:\n",
    "                    pickle.dump(val_data_copy, file)\n",
    "\n",
    "                print(f\"随机种子：{seeds[model_seed]}，第 {fold_idx + 1} 折 第 {retries + 1} 次训练 KS评分: {current_ks_score}, 上次KS评分：{previous_ks_score}\")\n",
    "\n",
    "                # 如果KS评分提升，则跳出重试循环\n",
    "                if current_ks_score > previous_ks_score:\n",
    "                    fold_oof_preds[val_idx] = val_pred\n",
    "                    test_pred_proba = predictor_auto.predict_proba(X_test).values[:, 1]\n",
    "                    #test_pred_proba1 = test_pred_proba.values\n",
    "                    #test_pred = test_pred_proba1[:, 1]\n",
    "                    fold_test_preds += test_pred_proba / fold\n",
    "                    previous_ks_score = current_ks_score\n",
    "                    print(f\"当前ks评分：{previous_ks_score}, 训练次数：{retries + 1}\")\n",
    "\n",
    "                    # 如果当前模型是目前最好的，保存模型路径和KS评分\n",
    "                    if current_ks_score > best_ks_score:\n",
    "                        best_ks_score = current_ks_score\n",
    "                        best_model_path = model_path\n",
    "\n",
    "                    break\n",
    "                else:\n",
    "                    # 特征重要性分析，选择影响较小的特征进行剔除\n",
    "                    print(f\"随机种子：{seeds[model_seed]}，第 {fold_idx + 1} 折 第 {retries + 1} 次训练的KS评分未提升，分析特征重要性并重新训练...\")\n",
    "                    feature_importance = predictor_auto.feature_importance(data=val_data_copy)\n",
    "                    least_important_feature = feature_importance.idxmin()  \n",
    "                    print(f\"剔除特征：{least_important_feature}，重要性值：{feature_importance.min()}\")\n",
    "                    current_features.remove(least_important_feature)  \n",
    "                    retries += 1\n",
    "\n",
    "            if retries == max_retries:\n",
    "                print(f\"随机种子：{seeds[model_seed]}，第 {fold_idx + 1} 折在最大重试次数下，最佳KS评分: {previous_ks_score}\")\n",
    "\n",
    "            # 计算当前折的训练时间和预计完成时间\n",
    "            fold_time_elapsed = time.time() - time.mktime(time.strptime(fold_start_time, '%Y-%m-%d %H:%M:%S'))\n",
    "            total_folds_remaining = (len(seeds) - seeds.index(seeds[model_seed]) - 1) * fold + (fold - fold_idx - 1)\n",
    "            estimated_time_remaining = total_folds_remaining * fold_time_elapsed\n",
    "            print(f\"随机种子：{seeds[model_seed]}，第 {fold_idx + 1} 折耗时：{fold_time_elapsed:.2f} 秒，预计剩余时间：{estimated_time_remaining / 60:.2f} 分钟\")\n",
    "\n",
    "        oof_preds += fold_oof_preds / num_model_seed\n",
    "        test_preds += fold_test_preds / num_model_seed\n",
    "        pred.append(fold_test_preds)\n",
    "\n",
    "    # 总训练时间\n",
    "    overall_time_elapsed = time.time() - time.mktime(time.strptime(overall_start_time, '%Y-%m-%d %H:%M:%S'))\n",
    "    print(f\"总训练时间：{overall_time_elapsed / 60:.2f} 分钟\")\n",
    "\n",
    "    # 输出最终的KS评分\n",
    "    final_ks_score = compute_ks(y_train, oof_preds)\n",
    "    print(f\"最终KS评分: {final_ks_score}\")\n",
    "\n",
    "    # 使用最佳模型对测试集进行预测\n",
    "    print(f\"最佳模型路径: {best_model_path}, 最佳KS评分: {best_ks_score}\")\n",
    "    best_model = TabularPredictor.load(best_model_path)\n",
    "    test_predictions = best_model.predict_proba(X_test)\n",
    "\n",
    "    # 返回测试集预测结果\n",
    "    return best_model_path, test_preds, oof_preds, pred"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 通用特征选择函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from lightgbm import LGBMClassifier\n",
    "from lightgbm import log_evaluation, early_stopping\n",
    "\n",
    "import lightgbm as lgb\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "def feature_selection_with_lgb_adversarial_optimized(X, y, seeds, collinearity_threshold=0.994, missing_threshold=0.994, \n",
    "                                                     unique_rate_threshold=0.994, adversarial_threshold=0.55, fold=5):\n",
    "    \"\"\"\n",
    "    使用多模型种子、交叉验证和LightGBM评估特征的对抗性AUC，实现稳健的特征选择。\n",
    "    \n",
    "    Args:\n",
    "    X (pd.DataFrame): 特征数据集。\n",
    "    y (pd.Series): 目标变量。\n",
    "    seeds (list): 多模型种子列表。\n",
    "    collinearity_threshold (float): 共线性剔除阈值。\n",
    "    missing_threshold (float): 缺失值率剔除阈值。\n",
    "    unique_rate_threshold (float): 重复率剔除阈值。\n",
    "    adversarial_threshold (float): 对抗性AUC阈值，用于识别区分度过高的特征。\n",
    "    fold (int): 交叉验证的折数。\n",
    "\n",
    "    Returns:\n",
    "    pd.DataFrame: 处理后的特征数据集。\n",
    "    list: 被剔除的特征名称。\n",
    "    \"\"\"\n",
    "    removed_features = []\n",
    "    feature_importance_df = pd.DataFrame({'feats': X.columns, 'imp': 0})\n",
    "\n",
    "    # 1. 剔除高缺失值率的特征\n",
    "    #missing_rate = X.isnull().mean()\n",
    "    #high_missing_cols = missing_rate[missing_rate > missing_threshold].index.tolist()\n",
    "    #removed_features.extend(high_missing_cols)\n",
    "    #X = X.drop(columns=high_missing_cols)\n",
    "    \n",
    "    # 2. 剔除高重复率的特征\n",
    "    unique_rate = X.apply(lambda col: col.nunique() / len(col))\n",
    "    high_unique_cols = unique_rate[unique_rate > unique_rate_threshold].index.tolist()\n",
    "    removed_features.extend(high_unique_cols)\n",
    "    X = X.drop(columns=high_unique_cols)\n",
    "\n",
    "    # 3. 剔除共线性较高的特征\n",
    "    corr_matrix = X.corr().abs()\n",
    "    upper_triangle = corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(bool))\n",
    "    collinear_cols = [column for column in upper_triangle.columns if any(upper_triangle[column] > collinearity_threshold)]\n",
    "    removed_features.extend(collinear_cols)\n",
    "    X = X.drop(columns=collinear_cols)\n",
    "    \n",
    "    # 4. 使用多种随机种子、交叉验证、LightGBM对抗性AUC评估\n",
    "    #adversarial_aucs = {}\n",
    "    #for seed in seeds:\n",
    "    #    skf = StratifiedKFold(n_splits=fold, random_state=seed, shuffle=True)\n",
    "    #    for index, (train_index, test_index) in enumerate(skf.split(X, y)):\n",
    "    #        # 对抗性目标\n",
    "    #        y_adversarial = pd.Series(np.random.permutation(y.values), index=X.index)\n",
    "    #        X_train, X_valid = X.iloc[train_index], X.iloc[test_index]\n",
    "    #        y_train, y_valid = y_adversarial.iloc[train_index], y_adversarial.iloc[test_index]\n",
    "    #        \n",
    "    #        # LightGBM参数\n",
    "    #        lgb_params = {\n",
    "    #            'learning_rate': 0.03,\n",
    "    #            'max_depth': -1,\n",
    "    #            'boosting_type': 'gbdt',\n",
    "    #            'objective': 'binary',\n",
    "    #            'metric': 'auc',\n",
    "    #            'num_leaves': 12,\n",
    "    #            'feature_fraction': 0.8,\n",
    "    #            'bagging_fraction': 0.8,\n",
    "    #            'bagging_freq': 5,\n",
    "    #            'seed': seed\n",
    "    #        }\n",
    "#\n",
    "    #        # 计算每个特征的对抗性AUC\n",
    "    #        for col in X.columns:\n",
    "    #            lgb_train = lgb.Dataset(X_train[[col]], label=y_train)\n",
    "    #            lgb_valid = lgb.Dataset(X_valid[[col]], label=y_valid, reference=lgb_train)\n",
    "    #            model = lgb.train(\n",
    "    #                lgb_params, lgb_train, num_boost_round=100,\n",
    "    #                valid_sets=[lgb_train, lgb_valid],\n",
    "    #                early_stopping_rounds=10, verbose_eval=False\n",
    "    #            )\n",
    "    #            preds = model.predict(X_valid[[col]], num_iteration=model.best_iteration)\n",
    "    #            adversarial_auc = roc_auc_score(y_valid, preds)\n",
    "    #            \n",
    "    #            # 累加特征重要性\n",
    "    #            feature_importance_df.loc[feature_importance_df['feats'] == col, 'imp'] += model.feature_importance() / fold\n",
    "    #            adversarial_aucs[col] = adversarial_aucs.get(col, 0) + (adversarial_auc / len(seeds))\n",
    "#\n",
    "    #        gc.collect()\n",
    "    #\n",
    "    ## 根据对抗性AUC阈值剔除区分度过高的特征\n",
    "    #adversarial_cols = [col for col, auc in adversarial_aucs.items() if auc > adversarial_threshold]\n",
    "    #removed_features.extend(adversarial_cols)\n",
    "    #X = X.drop(columns=adversarial_cols)\n",
    "    #\n",
    "    ## 返回处理后的数据集和被剔除的特征\n",
    "    return X#, removed_features, feature_importance_df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 数据准备"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "target_data = pd.concat([TARGET_T[['CUST_NO']], TARGET_B[['CUST_NO']]], axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_data = merge_with_target(target_data, df_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#df_data = df_data.loc[:, ~df_data.columns.duplicated()]\n",
    "#df_data.dropna(axis=1, how='all', inplace=True)\n",
    "#df_data_check = df_data.select_dtypes(include=['object'])\n",
    "#print(df_data_check.columns)\n",
    "#num_check_df = df_data.select_dtypes(include=[np.number])\n",
    "#has_inf = np.isinf(num_check_df.values).any()\n",
    "#print(has_inf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_data['finalcase_flag'].fillna(0, inplace=True)\n",
    "df_data['punishbreak_flag'].fillna(0, inplace=True)\n",
    "df_data['punished_flag'].fillna(0, inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_data['finalcase_flag'] = df_data['finalcase_flag'].astype(int)\n",
    "df_data['punishbreak_flag'] = df_data['punishbreak_flag'].astype(int)\n",
    "df_data['punished_flag'] = df_data['punished_flag'].astype(int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_data.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_data = TARGET_T[['CUST_NO', 'FLAG']].merge(df_data, on=\"CUST_NO\", how=\"left\")\n",
    "test_data =  TARGET_B[['CUST_NO']].merge(df_data, on=\"CUST_NO\", how=\"left\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "feature_name = [i for i in df_data.columns if i not in ['DATA_DAT', 'CUST_NO','FLAG']] \n",
    "\n",
    "X_train = train_data[feature_name].reset_index(drop=True)\n",
    "X_test = test_data[feature_name].reset_index(drop=True)\n",
    "y = train_data['FLAG'].reset_index(drop=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "seeds = [1993, 123]\n",
    "X_selected_clean = feature_selection_with_lgb_adversarial_optimized(X_train, y, seeds)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "feature_clean = X_selected_clean.columns\n",
    "\n",
    "X_train_clean = train_data[feature_clean].reset_index(drop=True)\n",
    "X_test_clean = test_data[feature_clean].reset_index(drop=True)\n",
    "y_clean = train_data['FLAG'].reset_index(drop=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_selected_clean.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model_path, test_preds_final, train_preds_final, fold_test_all = train_best_model(X_train_clean, y_clean, X_test_clean)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model_path, test_preds_final, train_preds_final, fold_test_all = train_best_model(X_train_clean, y_clean, X_test_clean)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model_path2, test_preds_final2, train_preds_final2, fold_test_all2 = train_best_model(X_train_clean, y_clean, X_test_clean)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ks(y_clean,train_preds_final2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Test_B = TARGET_B[['CUST_NO']]\n",
    "Test_B['FLAG'] = test_preds_final"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Test_B[['CUST_NO', 'FLAG']].head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "submission = Test_B[['CUST_NO', 'FLAG']]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "submission.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "submission.to_csv('upload_1104_B_2.csv', index=False, header=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "init_woody"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%predict 2 upload_1104_B_2.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%query_predict 2"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
